home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
JFC.bin
/
MacTreeUI.java
< prev
next >
Wrap
Text File
|
1998-06-30
|
18KB
|
685 lines
/*
* @(#)MacTreeUI.java 1.9 98/02/02
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing.plaf.mac;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import com.sun.java.swing.*;
import com.sun.java.swing.plaf.*;
import com.sun.java.swing.tree.*;
import com.sun.java.swing.plaf.basic.BasicTreeUI;
import com.sun.java.swing.plaf.basic.VisibleTreeNode;
import com.sun.java.swing.plaf.basic.LargeTreeModelNode;
/**
* <p>
* Warning: serialized objects of this class will not be compatible with
* future swing releases. The current serialization support is appropriate
* for short term storage or RMI between Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*
* @version @(#)MacTreeUI.java 1.0 11/24/97
* @author Symantec
*/
public class MacTreeUI extends BasicTreeUI implements java.awt.event.MouseMotionListener
{
protected static Icon collapsedPressedIcon = null;
protected static Icon expandedPressedIcon = null;
protected static Icon intermediateIcon = null;
protected static Color GSWColor = null;
public void installUI(JComponent c)
{
super.installUI(c);
isNodePressed = false;
isIntermediate = false;
wasStartedInControl = false;
wasInControl = false;
currentNode = null;
currentENode = null;
//Force the renderer to be queried for each row's height.
this.setRowHeight(-1);
}
public void uninstallUI(JComponent c)
{
super.uninstallUI(c);
mouseMotionListener = null;
}
public static ComponentUI createUI(JComponent x)
{
return new MacTreeUI();
}
/**
* Returns the default cell renderer that is used to do the
* stamping of each node.
*/
public TreeCellRenderer createDefaultCellRenderer()
{
return new MacTreeCellRenderer();
}
public void drawHorizontalPartOfLeg( Graphics g, JComponent c, int lineY, int leftX, int rightX )
{
//Do nothing
}
public void drawVerticalPartOfLeg( Graphics g, JComponent c, int depth, int parentY, int childY, int parentRowHeight, int childRowHeight )
{
//Do nothing
}
/**
* Invoked when a mouse button has been pressed on a component.
*/
public void mousePressed(MouseEvent e)
{
int row = getRow(e.getY());
wasStartedInControl = false;
if (row > -1 && row < this.getRowCount())
{
int rowLevel;
int childIndex = -1;
LargeTreeModelNode eNode = null;
VisibleTreeNode node = null;
if(!largeModel)
{
node = this.getNode(row);
rowLevel = node.getVisibleLevel();
}
else
{
if(row == 0 && isRootVisible())
{
eNode = largeRoot;
rowLevel = 0;
}
else
{
int[] cIndex = new int[1];
eNode = getLargeParentAndChildIndexOfRow(row, cIndex);
rowLevel = eNode.getVisibleLevel() + 1;
childIndex = cIndex[0];
}
}
if(clickedInExpandControl( row, rowLevel, e.getX(), e.getY() ))
{
if(largeModel)
currentENode = eNode;
else
currentNode = node;
wasStartedInControl = true;
isNodePressed = true;
paintCurrentNode();
}
}
}
/**
* Returns the x origin of the given node, which is based on whether
* or not we're showing handles and the visible level of the node
* multiplied by the right and left indent factor.
*/
public int getXOriginOfNode(VisibleTreeNode node)
{
int visibleLevel = node.getVisibleLevel();
if(this.getShowsRootHandles())
visibleLevel++;
return (totalChildIndent * visibleLevel) + xNodeAdjustment;
}
/**
* Invoked when a mouse button has been released on a component.
*/
public void mouseReleased(MouseEvent e)
{
int row = getRow(e.getY());
if (row > -1 && row < this.getRowCount())
{
int rowLevel;
int childIndex = -1;
LargeTreeModelNode eNode = null;
VisibleTreeNode node = null;
if(!largeModel)
{
node = this.getNode(row);
rowLevel = node.getVisibleLevel();
}
else
{
if(row == 0 && isRootVisible())
{
eNode = largeRoot;
rowLevel = 0;
}
else
{
int[] cIndex = new int[1];
eNode = getLargeParentAndChildIndexOfRow(row, cIndex);
rowLevel = eNode.getVisibleLevel() + 1;
childIndex = cIndex[0];
}
}
if(clickedInExpandControl( row, rowLevel, e.getX(), e.getY() ))
{
boolean isSameNode = false;
if(largeModel && currentENode != null)
isSameNode = currentENode.equals(eNode);
else if(currentNode != null)
isSameNode = currentNode.equals(node);
if(isSameNode && isNodePressed)
{
handleExpandControlClick( node, eNode, childIndex, row );
}
isNodePressed = false;
}
int x = e.getX();
// Perhaps they clicked the cell itself. If so, select it.
int cellLeftX;
if(this.getShowsRootHandles())
cellLeftX = (totalChildIndent * (rowLevel + 1)) + xNodeAdjustment;
else
cellLeftX = (totalChildIndent * rowLevel) + xNodeAdjustment;
if (x > cellLeftX)
{
int cellWidth;
if(!largeModel)
cellWidth = node.getPreferredSize().width;
else
cellWidth = getRowBounds(row).width;
if (x <= cellWidth + cellLeftX && !startEditing(getPathForRow(row), e))
{
int originalSelectedIndex;
originalSelectedIndex = lastSelectedRow;
if(originalSelectedIndex >= this.getRowCount() || !this.isSelectedIndex(originalSelectedIndex))
originalSelectedIndex = -1;
/* Control toggles just this node. */
if(e.isControlDown())
{
if(isSelectedIndex(row))
tree.removeSelectionInterval(row, row);
else
tree.addSelectionInterval(row, row);
if(originalSelectedIndex != -1)
lastSelectedRow = originalSelectedIndex;
}
/* Shift adjusts from the anchor point. */
else if(e.isShiftDown())
{
if(originalSelectedIndex == -1)
tree.addSelectionInterval(row, row);
else
{
if(row < originalSelectedIndex)
tree.setSelectionInterval(row, originalSelectedIndex);
else
tree.setSelectionInterval(originalSelectedIndex, row);
lastSelectedRow = originalSelectedIndex;
}
if(originalSelectedIndex != -1)
lastSelectedRow = originalSelectedIndex;
}
/* Otherwise set the selection to just this interval. */
else
{
tree.setSelectionInterval(row, row);
//!!! LAB !!! this seems insuficient to catch a double click properly.
if(e.getClickCount() == 2)
{
if(!largeModel)
{
node.toggleExpanded();
ensureRowsAreVisible(row, row + Math.min(10, node.visibleChildCount()));
}
else
{
if(childIndex == -1)
{
eNode.toggleExpanded();
ensureRowsAreVisible(row, row + Math.min(10, eNode.getTotalChildCount()));
}
else
{
if(!isExpanded(row))
expandRow(row);
else
collapseRow(row);
LargeTreeModelNode newNode;
newNode = getLargeTreeModelNodeForRow(row, false);
if(newNode != null)
ensureRowsAreVisible(row, row + Math.min(10, newNode.getTotalChildCount()));
else
ensureRowsAreVisible(row, row);
}
}
}
}
}
}
}
}
/**
* Handles Mouse Moved events
* @param e the MouseEvent
*/
public void mouseMoved(MouseEvent e)
{
}
/**
* Handles Mouse Dragged events
* @param e the MouseEvent
*/
public void mouseDragged(MouseEvent e)
{
trackControl(e);
}
public void handleExpandControlClick( VisibleTreeNode node, LargeTreeModelNode eNode,
int childIndex, int row )
{
animateCurrentControl();
super.handleExpandControlClick(node, eNode, childIndex, row );
paintCurrentNode();
}
protected void installDefaults( JComponent c )
{
super.installDefaults(c);
if(collapsedPressedIcon == null)
{
collapsedPressedIcon = (Icon) UIManager.getIcon("Tree.collapsedPressedIcon");
expandedPressedIcon = (Icon) UIManager.getIcon("Tree.expandedPressedIcon");
intermediateIcon = (Icon) UIManager.getIcon("Tree.intermediateIcon");
}
if(GSWColor == null)
{
GSWColor = UIManager.getColor("GrayscaleAppearanceW");
}
((JTree)c).setShowsRootHandles(((Boolean) UIManager.get("Tree.showsRootHandles")).booleanValue());
setRightChildIndent(16);
setLeftChildIndent(8);
}
protected void installListeners( JComponent c )
{
super.installListeners(c);
if ( (mouseMotionListener = createMouseMotionListener( c )) != null )
{
c.addMouseMotionListener( mouseMotionListener );
}
}
protected void uninstallListeners( JComponent c )
{
super.uninstallListeners(c);
if ( mouseMotionListener != null )
{
c.removeMouseMotionListener( mouseMotionListener );
}
}
protected MouseMotionListener createMouseMotionListener( JComponent c )
{
return this;
}
protected int getNodeX( VisibleTreeNode node )
{
int levelOffset = getShowsRootHandles() ? 1 : 0;
return ((node.getVisibleLevel() + levelOffset) * totalChildIndent) + xNodeAdjustment;
}
/**
* Handles tracking the mouse in the control while pressed.
*/
protected void trackControl(MouseEvent e)
{
if(wasStartedInControl)
{
if(pointInControl(currentNode, currentENode, e.getX(), e.getY()))
{
if(!wasInControl)
{
wasInControl = true;
isNodePressed = true;
paintCurrentNode();
}
}
else
{
if(wasInControl)
{
wasInControl = false;
isNodePressed = false;
paintCurrentNode();
}
}
}
}
/**
* Calculates the row of the tree based on the vertical component of a point.
* @return the row index.
*/
protected int getRow(int y)
{
int row;
checkConsistency();
if(tree != null && tree.isEnabled())
{
row = this.getRowContainingYLocation(y);
/* getRowContainingYLocation will return the last row,
even if outside of it, this insures it isn't beyond the
last row. */
if(row != -1)
{
Rectangle rect = getRowBounds(row);
if(y > (rect.y + rect.height))
{
row = -1;
}
}
}
else
row = -1;
return row;
}
/**
* Determines if a given point is inside a given node.
* @return true if the point is inside the given node,
* false if not.
*/
protected boolean pointInControl(VisibleTreeNode pNode, LargeTreeModelNode pENode, int x, int y)
{
int row = getRow(y);
if (row > -1 && row < this.getRowCount())
{
int rowLevel;
int childIndex = -1;
LargeTreeModelNode eNode = null;
VisibleTreeNode node = null;
if(!largeModel)
{
node = this.getNode(row);
rowLevel = node.getVisibleLevel();
}
else
{
if(row == 0 && isRootVisible())
{
eNode = largeRoot;
rowLevel = 0;
}
else
{
int[] cIndex = new int[1];
eNode = getLargeParentAndChildIndexOfRow(row, cIndex);
rowLevel = eNode.getVisibleLevel() + 1;
childIndex = cIndex[0];
}
}
boolean isSameNode = false;
if(largeModel && pENode != null)
isSameNode = pENode.equals(eNode);
else if(node != null && currentNode != null)
isSameNode = currentNode.equals(node);
if(clickedInExpandControl(row, rowLevel, x, y) && isSameNode)
return true;
}
return false;
}
protected void paintRow( Graphics g, JComponent c,
VisibleTreeNode parentNode, VisibleTreeNode childNode,
int childX, int childY,
int childRowHeight, int row )
{
g.setColor(GSWColor);
g.drawLine(0, childY + childRowHeight - 1, tree.getWidth() - 1, childY + childRowHeight - 1);
super.paintRow( g, c, parentNode, childNode, childX, childY, childRowHeight, row );
}
/**
* Draws the current node with the current node's parameters. i.e. is it pressed?
*/
protected void paintCurrentNode()
{
JComponent c = tree;
Graphics g = tree.getGraphics();
Point mid = getMiddleOfControl(currentNode);
if(largeModel && currentENode != null)
{
//??? LAB ??? What to do here?
}
else if(currentNode != null)
{
// Draw icons if not a leaf and either hasn't been loaded,
// or the model child count is > 0.
if (!currentNode.isLeaf() && (!currentNode.hasBeenExpanded() || currentNode.getModelChildCount() > 0))
{
if(isIntermediate)
{
if(intermediateIcon != null)
drawCentered( c, g, intermediateIcon, mid.x, mid.y );
}
else if (currentNode.isExpanded())
{
if(isNodePressed)
{
if(expandedPressedIcon != null)
drawCentered( c, g, expandedPressedIcon, mid.x, mid.y );
}
else
{
Icon expandedIcon = getExpandedIcon();
if(expandedIcon != null)
drawCentered( c, g, expandedIcon, mid.x, mid.y );
}
}
else
{
if(isNodePressed)
{
if(collapsedPressedIcon != null)
drawCentered( c, g, collapsedPressedIcon, mid.x, mid.y );
}
else
{
Icon collapsedIcon = getCollapsedIcon();
if(collapsedIcon != null)
drawCentered( c, g, collapsedIcon, mid.x, mid.y );
}
}
}
}
}
//Get the mid point of the current control.
protected Point getMiddleOfControl(VisibleTreeNode aNode)
{
Point mid = null;
int childY = 0;
int childRowHeight = 0;
if(aNode != null)
{
childY = aNode.getYOrigin();
childRowHeight = isFixedRowHeight() ? getRowHeight() : aNode.getPreferredSize().height;
// mid = new Point((getRightChildIndent() - 1), childY + (childRowHeight / 2));
}
mid = new Point(((totalChildIndent - 1) / 2) - 1 + xNodeAdjustment, childY + (childRowHeight / 2));
return mid;
}
protected boolean clickedInExpandControl( int row, int rowLevel, int mouseX, int mouseY )
{
int boxWidth;
int boxLeftX;
int boxRightX;
if(getExpandedIcon() != null)
boxWidth = getExpandedIcon().getIconWidth();
else
boxWidth = 8;
boxLeftX = (getMiddleOfControl(currentNode).x) - (boxWidth / 2);
boxRightX = boxLeftX + boxWidth;
if(!this.getShowsRootHandles() && rowLevel == 0)
return false;
return (mouseX >= boxLeftX && mouseX <= boxRightX);
}
//Animate the expansion or collapse of the control.
protected void animateCurrentControl()
{
if(intermediateIcon == null || currentNode == null)
return;
JComponent c = tree;
Graphics g = tree.getGraphics();
Color oldColor = g.getColor();
int iconWidth = intermediateIcon.getIconWidth();
int iconHeight = intermediateIcon.getIconHeight();
Point mid = getMiddleOfControl(currentNode);
isIntermediate = true;
try
{
g.setColor(c.getBackground());
g.fillRect(mid.x - iconWidth/2, mid.y - iconHeight/2, iconWidth, iconHeight);
paintCurrentNode();
try
{
Thread.sleep(20);
}
catch (InterruptedException exc) {}
g.fillRect(mid.x - iconWidth/2, mid.y - iconHeight/2, iconWidth, iconHeight);
g.setColor(oldColor);
}
finally
{
isIntermediate = false;
}
}
protected void paintExpandControl( Graphics g, JComponent c,
VisibleTreeNode parentNode,
VisibleTreeNode childNode,
int childX, int childY,
int childRowHeight, int row )
{
// Draw icons if not a leaf and either hasn't been loaded,
// or the model child count is > 0.
if (!childNode.isLeaf() && (!childNode.hasBeenExpanded() || childNode.getModelChildCount() > 0))
{
Point mid = getMiddleOfControl(childNode);
int middleXOfKnob = mid.x;
int middleYOfKnob = mid.y;
if (childNode.isExpanded())
{
Icon expandedIcon = getExpandedIcon();
if(expandedIcon != null)
drawCentered( c, g, expandedIcon, middleXOfKnob, middleYOfKnob );
}
else
{
Icon collapsedIcon = getCollapsedIcon();
if(collapsedIcon != null)
drawCentered( c, g, collapsedIcon, middleXOfKnob, middleYOfKnob );
}
}
}
protected int xNodeAdjustment = 4; //The number of pixels to add to the left edge.
protected boolean isIntermediate;
protected boolean wasStartedInControl;
protected boolean wasInControl;
protected boolean isNodePressed;
protected MouseMotionListener mouseMotionListener;
protected VisibleTreeNode currentNode;
protected LargeTreeModelNode currentENode;
}